<?php
// +-------------------------------------------------------------------------------
// | DingZone [ A Rapid Development Framework For Dingtalk ]
// +-------------------------------------------------------------------------------
// | EnterpriseCustomize.php v1.0
// |
// | Copyright (c) 2014-2018 http://www.heimalanshi.com All rights reserved.
// | Author : Jie
// | Date : 2018-08-22
// +-------------------------------------------------------------------------------


namespace app\core\model;


use think\Db;
use think\Model;

class EnterpriseCustomize {
    const ALL = "*";

    const TYPE_CSS = "css";
    const TYPE_JS = "js";
    const TYPE_LANG = 'lang';
    const TYPE_CONFIG = 'config';

    public static $TYPES = [
        self::TYPE_CSS => 'CSS',
        self::TYPE_JS => 'JavaScript',
        self::TYPE_LANG => '语言包',
        self::TYPE_CONFIG => '自定义配置'
    ];

    /**
     * 清理相关缓存
     *
     * @param $eid
     * @param $type
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public static function clearCache($eid, $type) {
        CacheKey::remove("customize", [
            'eid' => $eid,
            'type' => $type
        ], "core");
    }

    /**
     * 获取值
     *
     * @param $eid
     * @param $type
     * @param $name
     * @param $defaultVal
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getContent($eid, $type, $name, $defaultVal) {
        $nameItems = explode("/", $name);
        $module = $nameItems[0];
        $controller = $nameItems[1];
        $action = $nameItems[2];
        $langset = $nameItems[3];
        $name = $nameItems[4];

        $actionRows = self::getAllBy($eid, $module, $controller, $action, $langset, $type);

        foreach ($actionRows as $actionRow) {
            if ($actionRow['name'] == $name) {
                return $actionRow['content'];
            }
        }
        return $defaultVal;
    }

    /**
     * @param $eid
     * @param $module
     * @param $controller
     * @param $action
     * @param $langset
     * @param $type
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getAllBy($eid, $module, $controller, $action, $langset, $type) {
        $module = strtolower($module);
        $controller = strtolower($controller);
        $action = strtolower($action);
        $langset = strtolower($langset);
        $type = strtolower($type);
        $cacheKey = CacheKey::module("core")->type("customize")->tags([
            'eid' => $eid,
            'module' => $module,
            'controller' => $controller,
            'action' => $action,
            'langset' => $langset,
            'type' => $type
        ]);
        $actionRows = $cacheKey->getValue();
        if ($actionRows !== false) {
            return $actionRows;
        }

        $conditions = [
            'enterprise_id' => $eid,
            'is_deleted' => 0,
            'type' => $type
        ];
        $rows = Db::name("enterprise_customize")->where($conditions)->select();

        $actionRows = [];
        foreach ($rows as $row) {
            if ($row['module'] != $module && $row['module'] != self::ALL && $module != self::ALL) {
                continue;
            }
            if ($row['controller'] != $controller && $row['controller'] != self::ALL && $controller != self::ALL) {
                continue;
            }
            if ($row['action'] != $action && $row['action'] != self::ALL && $action != self::ALL) {
                continue;
            }
            if ($row['langset'] != $langset && $row['langset'] != self::ALL && $langset != self::ALL) {
                continue;
            }
            $actionRows[] = $row;
        }

        //按照生效范围进行排序
        self::_sortActionRows($actionRows);

        $cacheKey->setValue($actionRows);
        return $actionRows;
    }

    /**
     * 按照生效的优先级排序
     *
     * @param $actionRows
     */
    private static function _sortActionRows(&$actionRows) {
        if (empty($actionRows)) {
            return;
        }
        $count = count($actionRows);
        for ($i = 0; $i < $count - 1; $i++) {
            //记录第$i个元素后的所有元素最小值下标
            $min = $i;
            for ($j = $i + 1; $j < $count; $j++) {
                if (self::_cmpActionRow($actionRows[$j], $actionRows[$min]) < 0) {
                    $min = $j;
                }
            }
            if ($min != $i) {
                $temp = $actionRows[$min];
                $actionRows[$min] = $actionRows[$i];
                $actionRows[$i] = $temp;
            }
        }
    }

    /**
     * 比较两个actionRow
     *
     * @param $actionRow1
     * @param $actionRow2
     * @return int
     */
    private static function _cmpActionRow($actionRow1, $actionRow2) {
        $module1 = $actionRow1['module'];
        $controller1 = $actionRow1['controller'];
        $action1 = $actionRow1['action'];
        $lang1 = $actionRow1['langset'];

        $module2 = $actionRow2['module'];
        $controller2 = $actionRow2['controller'];
        $action2 = $actionRow2['action'];
        $lang2 = $actionRow2['langset'];

        if ($module1 != $module2) {
            if ($module1 == self::ALL) {
                return 1;
            }
            if ($module2 == self::ALL) {
                return -1;
            }
        }

        if ($controller1 != $controller2) {
            if ($controller1 == self::ALL) {
                return 1;
            }
            if ($controller2 == self::ALL) {
                return -1;
            }
        }

        if ($action1 != $action2) {
            if ($action1 == self::ALL) {
                return 1;
            }
            if ($action2 == self::ALL) {
                return -1;
            }
        }

        if ($lang1 != $lang2) {
            if ($lang1 == self::ALL) {
                return 1;
            }
            if ($lang2 == self::ALL) {
                return -1;
            }
        }

        return 0;
    }

}